pub mod callback;
pub mod reminder;
pub mod health;

use axum::{Router, routing::{get, post}, middleware, body::Body, http::Request, extract::MatchedPath};
use sqlx::SqlitePool;
use std::sync::Arc;
use crate::config::Config;
use crate::utils::MessageCache;
use utoipa::OpenApi;
use utoipa_swagger_ui::SwaggerUi;
use crate::api_doc::ApiDoc;
use tracing::info;

#[derive(Clone)]
pub struct AppState {
    pub pool: SqlitePool,
    pub config: Arc<Config>,
    pub msg_cache: MessageCache,
}

pub fn create_router(state: AppState) -> Router {
    // 创建 Swagger UI
    let swagger = SwaggerUi::new("/swagger-ui")
        .url("/api-docs/openapi.json", ApiDoc::openapi());
    
    Router::new()
        .route("/callback", get(callback::verify_url))
        .route("/callback", post(callback::handle_message))
        .route("/reminder", post(reminder::handle_reminder))
        .route("/health", get(health::health_check))
        .merge(swagger)
        .layer(middleware::from_fn(log_request))
        .with_state(state)
}

/// 请求日志中间件
async fn log_request(
    req: Request<Body>,
    next: middleware::Next,
) -> axum::response::Response {
    let method = req.method().clone();
    let uri = req.uri().clone();
    let matched_path = req
        .extensions()
        .get::<MatchedPath>()
        .map(|p| p.as_str().to_owned());
    
    info!("[HTTP] {} {} {:?}", method, uri, matched_path);
    
    let response = next.run(req).await;
    let status = response.status();
    
    info!("[HTTP] {} {} -> {}", method, uri, status);
    
    response
}
